from turtle import pu
import chess
import chess.svg
import chess.pgn
from svglib.svglib import svg2rlg                       # Convert CVG to PDF
from reportlab.graphics import renderPDF
import fitz                                             # Convert PDF to PNG
import os
from csv import reader
from random import choice
import glob
from PIL import Image
import random
import string

import import_puzzles
import xml.etree.ElementTree as ET
import re
from reportlab.graphics import renderPDF
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

from qiniu import Auth,put_file

from logger_config import logger
ak='123'
sk='3232-RwZJPxMMR8x'

def upload_to_qiniu(file_path):
    # Create a Qiniu Auth object
    q = Auth(ak, sk)
    # Generate a token for the upload
    # cow = Cow(ak, sk)
    # b = cow.get_bucket('chesspgnlib')
    # Upload the file
    bucket_name = 'chesspgnlib'
    key = file_path[4:]
    token = q.upload_token(bucket_name, key, 3600)
    localfile = file_path
    ret, info = put_file(token, key, localfile, version='v2')
    print(info)


    # Check if the upload was successful
   
    return f'http://sqe1xn71h.hb-bkt.clouddn.com/{key}'
 

def process_zhisaiwang_data(zhisai):
    # Initialize the search string
    search_number = 1
    while search_number <= 200:  # Adjust this limit as needed
        search_string = f"{search_number}."
        if search_string in zhisai:
            # Insert a newline before the first occurrence
            zhisai = zhisai.replace(search_string, f"\n{search_string}", 1)
            search_number += 1
        else:
            break  # Exit the loop if the search string is not found
    formatted_lines = []
    # print(zhisai)

    # logger.info(zhisai)
    for line in zhisai.split('\n'):
        # Add space after each period
        line = line.replace('.', '. ')
        # Add space between numbers and letters
        formatted_line = ''
        for i in range(len(line)):
            if i > 0 and line[i-1].isdigit() and ((line[i].isalpha() and line[i]!='X' and line[i]!='x') or line[i-1] == '.')  or ((line[i-1] == '+') and line[i].isalpha()):
                # print(1)
                formatted_line += ' '
                formatted_line += line[i]
            else:
                if i>2 and i+1 < len(line) and ((line[i] == 'O' and line[i+1] == '-') or (line[i-1] == 'O' and line[i-2]=='-')):
                    # print(2)
                    formatted_line += ' '
                    formatted_line += line[i]
                else:
                    if line[i-1] == '=' and line[i].isalpha():
                        # print(3)
                        formatted_line += line[i]
                        formatted_line += ' '
                    else:
                        # print(4)
                        formatted_line += line[i]
        # print(formatted_line)
        formatted_line += ' '
        formatted_lines.append(formatted_line)
    res = ''.join(formatted_lines).replace('  ', ' ',-1)
    logger.info(res)
    return res  # Return the formatted_lines


def choose_puzzle():

    print('Choosing puzzle...')
    # Imports full list of puzzles
    with open('lichess_puzzles.csv') as puzzles_csv:
        puzzles = reader(puzzles_csv)
        puzzles = list(puzzles)

    puzzle = choice(puzzles)
    return puzzle

def choose_puzzle(rating, count):

    print('Choosing puzzle...')
    puzzles=import_puzzles.choose_puzzle(rating, count)
    # Imports full list of puzzles
    # with open('lichess_puzzles.csv') as puzzles_csv:
    #     puzzles = reader(puzzles_csv)
    #     puzzles = list(puzzles)

    # puzzle = choice(puzzles)
    return puzzles

def create_puzzle_dictionary(puzzle):
    '''Creates a dictionary with all necessary puzzle values.'''
    return {'PUZZLE_CODE': puzzle[0],
            'PUZZLE_FEN': puzzle[1],
            'FIRST_MOVE': puzzle[2].split()[0],
            'FIRST_PUZZLE_MOVE': 'White' if puzzle[1].split()[-5] == 'b' else 'Black',
            'PUZZLE_RATING': puzzle[3],
            'PUZZLE_URL': puzzle[8]
            }


def play_first_move(puzzle_fen, move):
    '''Plays the first move, and updates the board state.
    This has the effect of setting up the puzzle for the position to solve.
    '''
    board = chess.Board(puzzle_fen)
    move = chess.Move.from_uci(move)
    board.push(move)

    return board


import chess
import chess.svg

def board_to_svg(board, ss , move, id, answer, color):
    '''Creates SVG of puzzle.
    The color palette is inspired by Lichess.com.
    '''
    # Checks the last move played
    last_move = chess.Move(chess.parse_square(move[0:2]), chess.parse_square(move[2:4]))
    arrows = [chess.svg.Arrow(chess.parse_square(move[0:2]), chess.parse_square(move[2:4]), color="#0000cccc")]
    # Generate base board SVG
    board_svg = chess.svg.board(board, size=880, lastmove=last_move, arrows=arrows,flipped=not board.turn, coordinates=False,
                            colors={
                                'square light': '#FFFFFF',
                                'square dark': '#B0B0B0',
                                'square light lastmove': '#808080',
                                'square dark lastmove': '#808080'}
                            )
    
    # Find the point to insert new elements (just before the last </g> tag)
    board_svg = board_svg.replace('viewBox="0 0 360 360"', 'viewBox="0 0 440 840"')
    # insert_point = board_svg.rfind('</g>')
    # if insert_point == -1:
    insert_point = board_svg.rfind('</svg>')
    ss = f"{color} {id}: {ss}______________________"
    # Prepare extra elements (circle and text)
    extra_elements = f'''
        <g>
            <!-- Text at the bottom -->
            <text 
                x="10" 
                y="380"
                text-anchor="left"
                dominant-baseline="middle"
                font-family="Arial"
                font-size="16"
                fill="black"
            >
                {ss}
            </text>
        </g>
         <g>
            <!-- Text at the bottom -->
            <text 
                x="200" 
                y="400"
                text-anchor="left"
                dominant-baseline="middle"
                font-family="Arial"
                font-size="16"
                transform="scale(-1, -1) translate(-600, -800)"
                fill="black"
            >
                {answer}
            </text>
        </g>
    '''

    
    # Insert new elements into the board SVG
    if insert_point != -1:
        board_svg = board_svg[:insert_point] + extra_elements + board_svg[insert_point:]
    
    # Optionally save for debugging
    # with open(f"debug_svg_{move}.svg", "w") as f:
    #     f.write(board_svg)
    
    return board_svg

def svg_to_pdfA4(board_svg, name, delFile):
    '''This function converts the SVG to PDF.
    I would convert the SVG to PNG directly, but due to the complexity of the chess SVG,
    there were frequent glitches. Convering to PDF first, then using a different library
    to convert to PNG, solves this problem.
    '''

    with open(f"{name}.svg", "w") as puzzle_svg:
        # Saves PDF to directory
        puzzle_svg.write(board_svg)
        # Converts SVG to PDF
        chess_pdf = svg2rlg(f'{name}.svg')
        page_width = 595  # A4宽度 (points)
        page_height = 842  # A4高度 (points)
       
       # 获取 SVG 的原始宽高
        svg_width = chess_pdf.width
        svg_height = chess_pdf.height

        scale_x = page_width / svg_width
        scale_y = page_height / svg_height
        scale_factor = min(scale_x, scale_y)  # 保持比例，选择较小的缩放比例

        chess_pdf.width = svg_width * scale_factor
        chess_pdf.height = svg_height * scale_factor
        chess_pdf.scale(scale_factor, scale_factor)

        c = canvas.Canvas(f'{name}.pdf', pagesize=A4)
        renderPDF.draw(chess_pdf, c, 40, -5)  # 调整坐标来放置图形
        c.save()
        # renderPDF.drawToFile(chess_pdf, f'{name}.pdf',40,0)
        # Delete SVG   
    if delFile:
        os.remove(f'{name}.svg')
    

def svg_to_pdf(board_svg, name, delFile):
    '''This function converts the SVG to PDF.
    I would convert the SVG to PNG directly, but due to the complexity of the chess SVG,
    there were frequent glitches. Convering to PDF first, then using a different library
    to convert to PNG, solves this problem.
    '''

    with open(f"{name}.svg", "w") as puzzle_svg:
        # Saves PDF to directory
        puzzle_svg.write(board_svg)
        # Converts SVG to PDF
        chess_pdf = svg2rlg(f'{name}.svg')
        renderPDF.drawToFile(chess_pdf, f'{name}.pdf')
        # Delete SVG
    if delFile:
        os.remove(f'{name}.svg')


def pdf_to_image(chess_pdf, name, delFile):
    '''This function converts the PDF to a PNG file,
    a format of media accepted by Twitter.
    '''

    chess_doc = fitz.open(chess_pdf)
    # 'Iterating' through the one-page document, and generating a map
    for page in chess_doc:
        # (3, 3) Guarantees high-resolution
        matrix = fitz.Matrix(3, 3)
        puzzle_picture = page.get_pixmap(matrix=matrix)
        puzzle_picture.save(f"{name}.png")
        convert_png_to_grayscale(f"{name}.png", f"{name}_grayscale.png")
    # Delete PDF, as it is no longer needed
    if delFile:
        os.remove(f'{name}.pdf')

    # os.remove(f'{name}.pdf')


def convert_png_to_grayscale(input_path: str, output_path: str):
    """Convert a PNG image to grayscale."""
    with Image.open(input_path) as img:
        grayscale_img = img.convert("L")
        grayscale_img.save(output_path)


def merge_svgs(svg_files, layout=(1, 1)):
    """
    将多个SVG文件合并成一个SVG文件
    
    Args:
        svg_files: SVG文件内容列表
        output_file: 输出文件路径
        layout: 布局元组 (行数, 列数)
    """
    rows, cols = layout
    board_size = 440  # 假设每个棋盘是 400x400
    
    # 创建主SVG
    merged_svg = f'''<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="{cols * board_size}" height="{rows * board_size}">
'''
    
    # 添加每个SVG的内容
    for i, svg_content in enumerate(svg_files):
        if i >= rows * cols:  # 确保不超过布局大小
            break
            
        row = i // cols
        col = i % cols
        x = col * board_size
        y = row * board_size
        
        # 提取SVG内容（去除头尾标签）
        content = svg_content.replace('<?xml version="1.0" encoding="UTF-8"?>', '')
        content = content.replace('<svg xmlns="http://www.w3.org/2000/svg"', f'<g transform="translate({x}, {y})"')
        content = content.replace('</svg>', '</g>')
        
        merged_svg += content
    
    merged_svg += '</svg>'
    
    # 保存文件
    return merged_svg


def cleanup_png_files():
    """
    删除当前目录下的所有PNG文件
    """
    # 删除所有.png文件
    for png_file in glob.glob("*.png"):
        try:
            os.remove(png_file)
            print(f"已删除: {png_file}")
        except Exception as e:
            print(f"删除 {png_file} 时出错: {str(e)}")
    for svg_file in glob.glob("*.svg"):
        try:
            os.remove(svg_file)
            print(f"已删除: {svg_file}")
        except Exception as e:
            print(f"删除 {png_file} 时出错: {str(e)}")
    for pdf_file in glob.glob("*.pdf"):
        try:
            os.remove(pdf_file)
            print(f"已删除: {pdf_file}")
        except Exception as e:
            print(f"删除 {pdf_file} 时出错: {str(e)}")

def oci_to_pgn(fen, uci_moves):
    # print(uci_moves)
    game = chess.pgn.Game()
    game.setup(fen)
    ucis=uci_moves.split(" ")
    node = game.add_variation(chess.Move.from_uci(ucis[0]))
    i = 1
    while i < len(ucis):
        node = node.add_variation(chess.Move.from_uci(ucis[i]))
        i += 1

    # 返回PGN格式
    s = str(game)
    # print('...............................')
    ss=s.split("\n")
    # print(ss[len(ss)-1])
    # print('...............................')
    return ss[len(ss)-1]

def getPuzzleA4(score):
    puzzles = choose_puzzle(score, 8)

    # Generates a dictionary with all important puzzle information
    # puzzle_dictionary = create_puzzle_dictionary(puzzle)
    # puzzle_code, puzzle_fen, first_move, first_puzzle_move, puzzle_rating, puzzle_url = puzzle_dictionary.values()

    # Create file name for puzzle
    
    svg_files = []
    i = 1
    for puzzle in puzzles:
        file_name = f"{puzzle['PuzzleId']}_{puzzle['Rating']}"
        color = puzzle['FEN'].split()[-5]
        if color == 'b':
            color = str(i)+'.White'
        else:
            color = str(i)+'.Black'
        
        board = play_first_move(puzzle['FEN'],  puzzle['Moves'].split()[0])
        ss = oci_to_pgn(puzzle['FEN'], puzzle['Moves'])
        ss = re.sub(r'\d+\.\.\.|\d+\.', '', ss)
        # print(ss)   
        # Generates board SVG, including highlighting the previous move
        board_csv = board_to_svg(board,  ss.split(" ")[1], puzzle['Moves'].split()[0], puzzle['Rating'], ss , color)
        svg_files.append(board_csv)
        # Converts SVG -> PDF -> PNG
        # svg_to_pdf(board_csv, file_name,True)
        # pdf_to_image(f'{file_name}.pdf', file_name,True)
        i += 1

    merged_svg = merge_svgs(svg_files, layout=(3, 2))
    # 生成随机字符串作为文件名前缀
    characters = string.ascii_letters + string.digits  # 包含大小写字母和数字
    filename = ''.join(random.choice(characters) for _ in range(12))
    filename = 'pgn/'+filename
    # filename1 = '/usr/share/nginx/html/'+filename
    print(filename)
    # 拼接前缀和扩展名
    svg_to_pdfA4(merged_svg, filename,True)
    pdf_to_image(f'{filename}.pdf', filename,True)
    res = filename+'_grayscale.png'
    url = upload_to_qiniu(res)
    logger.info(url)
    return url
def main():


    # 启动时清理PNG文件
    cleanup_png_files()

    print(getPuzzleA4(2000))

if __name__ == '__main__':
    main()